/**
 * entityExtractor.ts
 * 用于从文本中提取关键实体和重要概念
 * 这些实体将在智能历史压缩过程中被优先保留
 */

/**
 * 实体提取相关功能
 */

// 实体类型定义
export enum EntityType {
    PERSON = 'person',       // 人物
    LOCATION = 'location',   // 地点
    ORGANIZATION = 'organization', // 组织
    CONCEPT = 'concept',     // 概念
    TERM = 'term',           // 术语
    CUSTOM = 'custom'        // 自定义实体
}

// 实体对象接口
export interface Entity {
    text: string;            // 实体文本
    type: EntityType;        // 实体类型
    importance: number;      // 重要性评分 (0-10)
    frequency: number;       // 出现频率
    lastMentionedIndex: number; // 最后一次被提及的消息索引
    relatedEntities?: string[]; // 相关实体
}

// 实体管理器类
export class EntityManager {
    private entities: Map<string, Entity> = new Map();
    private entityPatterns: Map<EntityType, RegExp[]> = new Map();

    constructor() {
        this.initEntityPatterns();
    }

    // 初始化实体识别模式
    private initEntityPatterns() {
        // 人物识别模式
        this.entityPatterns.set(EntityType.PERSON, [
            /([A-Z][a-z]+(?:\s[A-Z][a-z]+)+)/g, // 英文人名 (例如: John Smith)
            /([赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨][\u4e00-\u9fa5]{1,2})/g, // 中文人名 (简化模式)
            /(?<=叫|名为|名字是|是|他是|她是|我是)[\u4e00-\u9fa5]{2,4}(?=的|，|。)/g // 上下文人名
        ]);

        // 地点识别模式
        this.entityPatterns.set(EntityType.LOCATION, [
            /([A-Z][a-z]+(?:\s[A-Z][a-z]+)*(?:\s(?:City|Town|Village|Mountain|River|Lake|Ocean|Sea|Forest|Desert|Island|Valley|Hill)))/g, // 英文地名
            /[\u4e00-\u9fa5]{2,4}(?:国|市|省|县|镇|村|山|河|湖|海|岛|谷|峰)/g // 中文地名
        ]);

        // 组织识别模式
        this.entityPatterns.set(EntityType.ORGANIZATION, [
            /([A-Z][a-z]*(?:\s[A-Z][a-z]*)*(?:\s(?:Company|Corporation|Inc|Ltd|Organization|Association|University|College|School|Institute|Agency|Bureau|Department)))/g, // 英文组织名
            /[\u4e00-\u9fa5]{2,10}(?:公司|集团|组织|协会|大学|学院|学校|研究所|研究院|局|部|厅|中心)/g // 中文组织名
        ]);

        // 概念识别模式
        this.entityPatterns.set(EntityType.CONCEPT, [
            /([A-Z][a-z]+(?:\s[A-Z][a-z]+)*(?:\s(?:Theory|Method|Approach|Concept|Principle|Law|Effect|Phenomenon|System|Structure|Process)))/g, // 英文概念名
            /[\u4e00-\u9fa5]{2,8}(?:理论|方法|概念|原理|法则|效应|现象|系统|结构|过程)/g // 中文概念名
        ]);

        // 术语识别模式
        this.entityPatterns.set(EntityType.TERM, [
            /\b([A-Za-z]+(?:-[A-Za-z]+)*)\b(?=\s+is\s+a\s+|，是一种|，是一个)/g, // 定义上下文
            /"([^"]+)"/g,  // 引号中的内容可能是术语
            /'([^']+)'/g,  // 单引号中的内容
            /「([^」]+)」/g, // 中文引号
            /『([^』]+)』/g  // 中文书名号
        ]);
    }

    /**
     * 从文本中提取关键实体
     * @param text 要分析的文本
     * @param messageIndex 消息在对话历史中的索引 (用于记录最后提及位置)
     * @returns 提取的实体列表
     */
    public extractEntities(text: string, messageIndex: number): Entity[] {
        const foundEntities: Entity[] = [];

        // 遍历所有实体类型的模式
        for (const [entityType, patterns] of this.entityPatterns.entries()) {
            for (const pattern of patterns) {
                // 重置正则表达式
                pattern.lastIndex = 0;
                let match;

                // 查找所有匹配项
                while ((match = pattern.exec(text)) !== null) {
                    const entityText = match[1] || match[0];

                    // 排除过短的实体 (可能是误判)
                    if (entityText.length < 2) continue;

                    // 查找或创建实体
                    let entity = this.entities.get(entityText);

                    if (entity) {
                        // 更新已存在的实体
                        entity.frequency += 1;
                        entity.lastMentionedIndex = messageIndex;
                        // 增加重要性 (频繁提及的实体更重要)
                        entity.importance = Math.min(10, entity.importance + 0.5);
                    } else {
                        // 创建新实体
                        entity = {
                            text: entityText,
                            type: entityType,
                            importance: this.calculateInitialImportance(entityText, entityType),
                            frequency: 1,
                            lastMentionedIndex: messageIndex
                        };

                        this.entities.set(entityText, entity);
                    }

                    foundEntities.push(entity);
                }
            }
        }

        return foundEntities;
    }

    /**
     * 计算实体的初始重要性
     * @param text 实体文本
     * @param type 实体类型
     * @returns 初始重要性评分 (0-10)
     */
    private calculateInitialImportance(text: string, type: EntityType): number {
        // 基础重要性分数
        let score = 5;

        // 根据类型调整
        switch (type) {
            case EntityType.PERSON:
                score += 1; // 人物通常更重要
                break;
            case EntityType.CONCEPT:
                score += 1.5; // 概念对上下文理解很关键
                break;
            case EntityType.TERM:
                score += 0.5; // 术语可能是专业内容
                break;
            default:
                break;
        }

        // 根据文本长度调整 (较长的实体通常更具体/重要)
        if (text.length > 10) {
            score += 0.5;
        } else if (text.length < 3) {
            score -= 1;
        }

        // 确保评分在合理范围内
        return Math.max(1, Math.min(10, score));
    }

    /**
     * 获取所有已识别的实体
     * @returns 所有实体的数组
     */
    public getAllEntities(): Entity[] {
        return Array.from(this.entities.values());
    }

    /**
     * 获取最重要的实体
     * @param limit 返回的最大实体数量
     * @returns 按重要性排序的实体数组
     */
    public getImportantEntities(limit: number = 10): Entity[] {
        return this.getAllEntities()
            .sort((a, b) => b.importance - a.importance)
            .slice(0, limit);
    }

    /**
     * 获取最近提及的实体
     * @param limit 返回的最大实体数量
     * @returns 按最后提及索引排序的实体数组
     */
    public getRecentEntities(limit: number = 10): Entity[] {
        return this.getAllEntities()
            .sort((a, b) => b.lastMentionedIndex - a.lastMentionedIndex)
            .slice(0, limit);
    }

    /**
     * 添加自定义实体 (人工指定的重要概念)
     * @param text 实体文本
     * @param importance 重要性 (0-10)
     * @param type 实体类型 (默认为CUSTOM)
     */
    public addCustomEntity(text: string, importance: number = 8, type: EntityType = EntityType.CUSTOM): void {
        this.entities.set(text, {
            text,
            type,
            importance,
            frequency: 1,
            lastMentionedIndex: 0
        });
    }

    /**
     * 从文本中识别并找出与已知实体匹配的部分
     * @param text 要分析的文本
     * @returns 文本中出现的已知实体
     */
    public findEntitiesInText(text: string): Entity[] {
        const result: Entity[] = [];

        for (const entity of this.entities.values()) {
            if (text.includes(entity.text)) {
                result.push(entity);
            }
        }

        return result;
    }

    /**
     * 清除所有实体记录
     */
    public clearEntities(): void {
        this.entities.clear();
    }
}

// 单例实例，用于在整个应用中共享实体管理器
export const entityManager = new EntityManager();

/**
 * 提取文本中的关键实体
 * @param text 要分析的文本
 * @param messageIndex 消息在对话历史中的索引
 * @returns 提取的实体列表
 */
export function extractEntities(text: string, messageIndex: number): Entity[] {
    return entityManager.extractEntities(text, messageIndex);
}

/**
 * 获取最重要的实体列表
 * @param limit 返回的最大实体数量
 * @returns 按重要性排序的实体数组
 */
export function getImportantEntities(limit: number = 10): Entity[] {
    return entityManager.getImportantEntities(limit);
} 